﻿namespace Snipps.Infrastructure.Services
{
    using System;
    using System.Threading;
    using System.Threading.Tasks;

    public class TasksThreadingService : IThreadingService
    {
        public Action QueueExecution<T>(Func<T> work, Action<T> completionCallback, Action<Exception> exceptionCallback)
        {
            var tokenSource = new CancellationTokenSource();
            var cancellationToken = tokenSource.Token;
            var sheduler = TaskScheduler.FromCurrentSynchronizationContext();
            var t = Task<T>.Factory.StartNew(work, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);

            t.ContinueWith(
                task => exceptionCallback(task.Exception.InnerException), 
                cancellationToken, 
                TaskContinuationOptions.OnlyOnFaulted, 
                sheduler);

            t.ContinueWith(
                task => completionCallback(task.Result), cancellationToken, TaskContinuationOptions.OnlyOnRanToCompletion, sheduler);

            return tokenSource.Cancel;
        }

        public Action QueueExecution(Action work, Action completionCallback, Action<Exception> exceptionCallback = null)
        {
            var tokenSource = new CancellationTokenSource();
            var cancellationToken = tokenSource.Token;
            var sheduler = TaskScheduler.FromCurrentSynchronizationContext();
            var t = Task.Factory.StartNew(work, cancellationToken, TaskCreationOptions.None, TaskScheduler.Default);

            if (exceptionCallback != null)
            {
                t.ContinueWith(
                    task => exceptionCallback(task.Exception.InnerException), 
                    cancellationToken, 
                    TaskContinuationOptions.OnlyOnFaulted, 
                    sheduler);
            }

            t.ContinueWith(
                task => completionCallback(), cancellationToken, TaskContinuationOptions.OnlyOnRanToCompletion, sheduler);

            return tokenSource.Cancel;
        }
    }
}